#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <ctime>

#include <GL/glew.h>
#include <GL/glut.h>

#include "card.h"
#include "cardMenu.h"
#include "string3d.h"
#include "shaders.h"

//Functions
char init();
void handleResize(int w, int h);
void update(int value); void handleKeypress(unsigned char key, int x, int y);
void handleKeyrelease(unsigned char key, int x, int y);
void drawScene();

int every;

/* The game is divined into "cards". Each card defines a "3d world".
 * The class Card is abstruct, the Card::card pointer should only point to 
 * subclasses of it.
 * Each subclass defines the details of its 3d world and how to draw it.
 * Card has an `update()` function, that is called once every frame, 
 * and may change the card's type (which instance the pointer is pointing to).
 * It also has a `draw()` function that draws itself.
 */
int main(int argc, char** argv)
{
	//Initialize GLUT
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
	glutInitWindowSize(800, 400);

	//Create window
	glutCreateWindow("dargite3d");
	if (init())
	{
		fprintf(stderr, "Error initializing game!\n");
		return -1;
	}

	//Initialize card
	Card::card = new CardMenu;

	//Handlers
	glutReshapeFunc(handleResize);
	glutKeyboardFunc(handleKeypress);
	glutKeyboardUpFunc(handleKeyrelease);
	glutDisplayFunc(drawScene);

	//Start update
	glutTimerFunc(25, update, 0);

	//Main loop
	glutMainLoop();
	return 0;
}

char init()
{
	//Init glew
	glewInit();

	//Use for drawing everything depending on z
	glEnable(GL_DEPTH_TEST);
	//glEnable(GL_CULL_FACE);

	//Clear color
	glClearColor(0.7f, 0.9f, 1.0f, 1.0f);

	//Init string
	string3d::init();

	//Ignore this (DEBUG)
	every = 30;

	//Shaders
	GLuint program = load_program("shaders/vertex.glsl", "shaders/fragment.glsl");
	if (!program) return -1;
	glUseProgram(program);

	//Everything is ok
	return 0;
}

void handleResize(int w, int h)
{
	//Tell openGL how to convert from coordinates to pixel values
	glViewport(0, 0, w, h);

	glMatrixMode(GL_PROJECTION); //switch to setting camera perspective

	//Set camera perspective
	glLoadIdentity(); //Reset camera
	gluPerspective(45.0,					//Camera angle
					(double)w / (double)h,	//width-to-height ratio
					1.0,					//near z clipping coordinate
					200.0);					//far z clipping coordinate
}

void handleKeypress(unsigned char key, int x, int y)
{
	//Pass input to card
	Card::card->input(key, 1);
}

void handleKeyrelease(unsigned char key, int x, int y)
{
	//Pass input to card
	Card::card->input(key, 0);
}

void update(int value)
{
	//Update
	Card::card->update();

	//Re-draw
	glutPostRedisplay();

	//Run again in 25 milliseconds
	glutTimerFunc(25, update, 0);
}

void drawScene()
{
	//Get frame start
	//clock_t start = clock();

	//Clear
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	//Modelview
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	//Card
	Card::card->draw();

	//Swap buffers
	glutSwapBuffers();

	//glFinish();

	//Calculate frame end
	/*clock_t elapsed = clock() -start;
	if (++every >= 10)
	{
		printf("%d\n", elapsed);
		every = 0;
	}*/
}
